package com.golxen.framework.timers;


import com.golxen.framework.executor.ThreadPlugin;
import com.golxen.utils.LogUtil;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.function.LongSupplier;

public class TimerStartor {
	Class<?> cls;
	long initialDelay;
	long delay;
	TimeUnit unit;
	int idx = -1;

	// 由于注册到真正启动定时有一定的时间误差，所以每日重置类的initialDelay待到真正启动时再算值
	LongSupplier initialDelayFn;

	List<ScheduledFuture<?>> futures = new ArrayList<>();

	public TimerStartor(Class<?> cls, LongSupplier initialDelayFn, long delay, TimeUnit unit) {
		this.cls = cls;
		this.initialDelayFn = initialDelayFn;
		this.delay = delay;
		this.unit = unit;
	}

	public TimerStartor(Class<?> cls, long initialDelay, long delay, TimeUnit unit) {
		this.cls = cls;
		this.initialDelay = initialDelay;
		this.delay = delay;
		this.unit = unit;
	}

	public TimerStartor(Class<?> cls, long initialDelay, long delay, TimeUnit unit, int idx) {
		this(cls, initialDelay, delay, unit);
		this.idx = idx;
	}

	public void start() {
		try {

			if (initialDelayFn != null) {
				initialDelay = initialDelayFn.getAsLong();
			}

			ScheduledFuture<?> future = null;
			if (this.idx == -1) {
				Runnable r = (Runnable) cls.newInstance();
				future = ThreadPlugin.getTimerExecutorService().scheduleAtFixedRate(r, initialDelay, delay, unit);
			} else {
				//传参数
				Constructor<?> constructor = cls.getConstructor(int.class);
				Runnable r = (Runnable) constructor.newInstance(idx);
				future = ThreadPlugin.getTimerExecutorService().scheduleAtFixedRate(r, initialDelay, delay, unit);
			}

			futures.add(future);
			LogUtil.COMMON.info("[Timer] start {} {}", cls.getName(), idx);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	public void stop() {
		for (ScheduledFuture<?> scheduledFuture : futures) {
			scheduledFuture.cancel(true);
		}
	}

	@Override
	public boolean equals(Object obj) {
		TimerStartor ts = (TimerStartor) obj;
		return this.cls.equals(ts.cls) && this.idx == ts.idx;
	}

}
